// SPDX-License-Identifier: GPL-2.0 OR Apache 2.0
/*
 * Copyright (c) 2024 Black Sesame Technologies
 *
 * This program is also distributed under the terms of the Apache 2.0
 * License.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* This file is auto generated for message box v1.1.0.
 * All manual modifications will be LOST by next generation.
 * It is recommended NOT modify it.
 * Generator Version: francaidl c4b9707 msgbx_ipc 1964fef
 */

#include "switch0_can_gateway_server.h"
#ifdef IPC_RTE_KERNEL
#include <bst/ipc_trans_common.h>
#include <bst/ipc_trans_layer.h>
#else
#include "ipc_trans_common.h"
#include "ipc_trans_layer.h"
#endif

// macro definitions
#define MAJOR 1U
#define MINOR 0U

#define MAX_METHOD_NUM 10U
#define MAX_BROADCAST_NUM 10U

#define CMD_METHOD_NOTIFY_ETH_2_CAN_ENQUEUE 1U
#define CMD_METHOD_NOTIFY_ETH_2_CAN_DEQUEUE 2U
#define CMD_METHOD_NOTIFY_CAN_2_ETH_ENQUEUE 3U
#define CMD_METHOD_NOTIFY_CAN_2_ETH_DEQUEUE 4U
#define CMD_METHOD_VMAC_METHOD 5U
#define CMD_METHOD_GET_ETH_STATISTICS 6U
#define CMD_METHOD_VCAN_METHOD 7U
#define CMD_METHOD_CAN_GATEWAY_SEND 8U

#define CMD_METHOD_SUB_CAN_GATEWAY_RECV 10U
#define CMD_METHOD_UNSUB_CAN_GATEWAY_RECV 11U
#define CMD_BROADCAST_CAN_GATEWAY_RECV 1U

// local variables
static com_server_data_t *s_data = NULL;
static switch0_can_gateway_server_ext_t *s_ext = NULL;

// interface implementation
// get interface version
static ipc_inf_version_t get_ipc_inf_version(void)
{
	ipc_inf_version_t ret = { .major = MAJOR, .minor = MINOR };

	return ret;
}

// method

static int32_t register_notify_Eth_2_Can_enqueue(switch0_can_gateway_notify_Eth_2_Can_enqueue_t func)
{
	if (!s_ext)
		return -ERR_APP_PARAM;
	s_ext->notify_Eth_2_Can_enqueue_ptr = func;
	return RESULT_SUCCESS;
}

static int32_t call_notify_Eth_2_Can_enqueue(serdes_t *des)
{
	int32_t ret = 0;
	des_buf_t *buf = NULL;
	uint32_t len = 0;
	com_server_data_t *data = s_data;
	uint32_t element_ptr = 0;
	uint16_t element_count = 0;

	if (!des || !data || !s_ext || !s_ext->notify_Eth_2_Can_enqueue_ptr)
		return -ERR_APP_PARAM;

	buf = &data->des_buf;
	clear_des_buf(buf);
	len = ipc_des_get_all(des, (uint8_t *)buf->data_buf);
	if (len <= 0)
		return -ERR_APP_SERDES;
	buf->unavail_data_size = IPC_MAX_DATA_SIZE - len;

	if (ret >= 0)
		ret = deserialize_32(buf, (uint32_t *)&element_ptr);
	if (ret >= 0)
		ret = deserialize_16(buf, (uint16_t *)&element_count);

	if (ret < 0)
		return -ERR_APP_SERDES;

	data->info.uuid = ipc_msg_get_uuid(des->header);
	data->info.timestamp = des->recv_end_time;
	(*s_ext->notify_Eth_2_Can_enqueue_ptr)(element_ptr, element_count, &data->info);

	return RESULT_SUCCESS;
}

static int32_t register_notify_Eth_2_Can_dequeue(switch0_can_gateway_notify_Eth_2_Can_dequeue_t func)
{
	if (!s_ext)
		return -ERR_APP_PARAM;
	s_ext->notify_Eth_2_Can_dequeue_ptr = func;
	return RESULT_SUCCESS;
}

static int32_t call_notify_Eth_2_Can_dequeue(serdes_t *des)
{
	int32_t ret = 0;
	des_buf_t *buf = NULL;
	uint32_t len = 0;
	com_server_data_t *data = s_data;
	uint32_t element_ptr = 0;
	uint16_t element_count = 0;

	if (!des || !data || !s_ext || !s_ext->notify_Eth_2_Can_dequeue_ptr)
		return -ERR_APP_PARAM;

	buf = &data->des_buf;
	clear_des_buf(buf);
	len = ipc_des_get_all(des, (uint8_t *)buf->data_buf);
	if (len <= 0)
		return -ERR_APP_SERDES;
	buf->unavail_data_size = IPC_MAX_DATA_SIZE - len;

	if (ret >= 0)
		ret = deserialize_32(buf, (uint32_t *)&element_ptr);
	if (ret >= 0)
		ret = deserialize_16(buf, (uint16_t *)&element_count);

	if (ret < 0)
		return -ERR_APP_SERDES;

	data->info.uuid = ipc_msg_get_uuid(des->header);
	data->info.timestamp = des->recv_end_time;
	(*s_ext->notify_Eth_2_Can_dequeue_ptr)(element_ptr, element_count, &data->info);

	return RESULT_SUCCESS;
}

static int32_t register_notify_Can_2_Eth_enqueue(switch0_can_gateway_notify_Can_2_Eth_enqueue_t func)
{
	if (!s_ext)
		return -ERR_APP_PARAM;
	s_ext->notify_Can_2_Eth_enqueue_ptr = func;
	return RESULT_SUCCESS;
}

static int32_t call_notify_Can_2_Eth_enqueue(serdes_t *des)
{
	int32_t ret = 0;
	des_buf_t *buf = NULL;
	uint32_t len = 0;
	com_server_data_t *data = s_data;
	uint32_t element_ptr = 0;
	uint16_t element_count = 0;

	if (!des || !data || !s_ext || !s_ext->notify_Can_2_Eth_enqueue_ptr)
		return -ERR_APP_PARAM;

	buf = &data->des_buf;
	clear_des_buf(buf);
	len = ipc_des_get_all(des, (uint8_t *)buf->data_buf);
	if (len <= 0)
		return -ERR_APP_SERDES;
	buf->unavail_data_size = IPC_MAX_DATA_SIZE - len;

	if (ret >= 0)
		ret = deserialize_32(buf, (uint32_t *)&element_ptr);
	if (ret >= 0)
		ret = deserialize_16(buf, (uint16_t *)&element_count);

	if (ret < 0)
		return -ERR_APP_SERDES;

	data->info.uuid = ipc_msg_get_uuid(des->header);
	data->info.timestamp = des->recv_end_time;
	(*s_ext->notify_Can_2_Eth_enqueue_ptr)(element_ptr, element_count, &data->info);

	return RESULT_SUCCESS;
}

static int32_t register_notify_Can_2_Eth_dequeue(switch0_can_gateway_notify_Can_2_Eth_dequeue_t func)
{
	if (!s_ext)
		return -ERR_APP_PARAM;
	s_ext->notify_Can_2_Eth_dequeue_ptr = func;
	return RESULT_SUCCESS;
}

static int32_t call_notify_Can_2_Eth_dequeue(serdes_t *des)
{
	int32_t ret = 0;
	des_buf_t *buf = NULL;
	uint32_t len = 0;
	com_server_data_t *data = s_data;
	uint32_t element_ptr = 0;
	uint16_t element_count = 0;

	if (!des || !data || !s_ext || !s_ext->notify_Can_2_Eth_dequeue_ptr)
		return -ERR_APP_PARAM;

	buf = &data->des_buf;
	clear_des_buf(buf);
	len = ipc_des_get_all(des, (uint8_t *)buf->data_buf);
	if (len <= 0)
		return -ERR_APP_SERDES;
	buf->unavail_data_size = IPC_MAX_DATA_SIZE - len;

	if (ret >= 0)
		ret = deserialize_32(buf, (uint32_t *)&element_ptr);
	if (ret >= 0)
		ret = deserialize_16(buf, (uint16_t *)&element_count);

	if (ret < 0)
		return -ERR_APP_SERDES;

	data->info.uuid = ipc_msg_get_uuid(des->header);
	data->info.timestamp = des->recv_end_time;
	(*s_ext->notify_Can_2_Eth_dequeue_ptr)(element_ptr, element_count, &data->info);

	return RESULT_SUCCESS;
}

static int32_t register_vmac_method(switch0_can_gateway_vmac_method_t func)
{
	if (!s_ext)
		return -ERR_APP_PARAM;
	s_ext->vmac_method_ptr = func;
	return RESULT_SUCCESS;
}

static int32_t call_vmac_method(serdes_t *des)
{
	int32_t ret = 0;
	des_buf_t *buf = NULL;
	uint32_t len = 0;
	com_server_data_t *data = s_data;
	uintptr_t pcon = 0;
	switch0_can_gateway_MyArray_t vmac_msg = { 0 };
	uint32_t flag = 0;

	if (!des || !data || !s_ext || !s_ext->vmac_method_ptr)
		return -ERR_APP_PARAM;

	buf = &data->des_buf;
	clear_des_buf(buf);
	len = ipc_des_get_all(des, (uint8_t *)buf->data_buf);
	if (len <= 0)
		return -ERR_APP_SERDES;
	buf->unavail_data_size = IPC_MAX_DATA_SIZE - len;

	if (ret >= 0)
		ret = deserialize_switch0_can_gateway_MyArray(buf, &vmac_msg);
	if (ret >= 0)
		ret = deserialize_32(buf, (uint32_t *)&flag);

	if (ret < 0)
		return -ERR_APP_SERDES;

	data->info.uuid = ipc_msg_get_uuid(des->header);
	data->info.timestamp = des->recv_end_time;
	pcon = (uintptr_t)&des->header;
	(*s_ext->vmac_method_ptr)(vmac_msg, flag, *(uint64_t *)pcon, &data->info);

	return RESULT_SUCCESS;
}

static int32_t reply_vmac_method(
				const switch0_can_gateway_ErrorEnum_t err,
				const uint64_t context)
{
	int32_t ret = 0;
#ifdef IPC_RTE_BAREMETAL
	serdes_t *ser = NULL;
#else
	serdes_t serdes = { 0 };
	serdes_t *ser = &serdes;
#endif
	com_server_data_t *data = s_data;
	uintptr_t pcon = (uintptr_t)&context;

	if (!data)
		return -ERR_APP_PARAM;
#ifdef IPC_RTE_BAREMETAL
	ser = &data->serializer;
#endif
	ret = ipc_ser_init(ser);
	if (ret >= 0)
		ret = serialize_switch0_can_gateway_ErrorEnum(ser, &err);

	if (ret < 0) {
		int32_t _err = -1;
		(void)ipc_ser_init(ser);
		ret = ipc_ser_put_32(ser, (uint32_t *)&_err);
		IPC_LOG_ERR("serialization failed.\n");
	}

	if (ret >= 0) {
		ser->header = *(rw_msg_header_t *)pcon;
		ser->header.cid = ser->header.pid;
		ser->header.pid = data->pid;
		ser->header.typ = MSGBX_MSG_TYPE_REPLY;
		ret = ipc_ser_finish(ser);
	}

	if (ret >= 0)
		ret = ipc_trans_layer_stub_send_reply_msg(data->pid, data->handle, ser);

	if (ret < 0) {
		IPC_LOG_ERR("send reply fail %d.\n", ret);
		return ret;
	}

	return RESULT_SUCCESS;
}

static int32_t register_get_ETH_statistics(switch0_can_gateway_get_ETH_statistics_t func)
{
	if (!s_ext)
		return -ERR_APP_PARAM;
	s_ext->get_ETH_statistics_ptr = func;
	return RESULT_SUCCESS;
}

static int32_t call_get_ETH_statistics(serdes_t *des)
{
	com_server_data_t *data = s_data;
	uintptr_t pcon = 0;

	if (!des || !data || !s_ext || !s_ext->get_ETH_statistics_ptr)
		return -ERR_APP_PARAM;

	data->info.uuid = ipc_msg_get_uuid(des->header);
	data->info.timestamp = des->recv_end_time;
	pcon = (uintptr_t)&des->header;
	(*s_ext->get_ETH_statistics_ptr)(*(uint64_t *)pcon, &data->info);

	return RESULT_SUCCESS;
}

static int32_t reply_get_ETH_statistics(
				const uint32_t statistics_data_ptr,
				const switch0_can_gateway_ErrorEnum_t err,
				const uint64_t context)
{
	int32_t ret = 0;
#ifdef IPC_RTE_BAREMETAL
	serdes_t *ser = NULL;
#else
	serdes_t serdes = { 0 };
	serdes_t *ser = &serdes;
#endif
	com_server_data_t *data = s_data;
	uintptr_t pcon = (uintptr_t)&context;

	if (!data)
		return -ERR_APP_PARAM;
#ifdef IPC_RTE_BAREMETAL
	ser = &data->serializer;
#endif
	ret = ipc_ser_init(ser);
	if (ret >= 0)
		ret = serialize_switch0_can_gateway_ErrorEnum(ser, &err);
	if (ret >= 0)
		ret = ipc_ser_put_32(ser, (uint32_t *)&statistics_data_ptr);

	if (ret < 0) {
		int32_t _err = -1;
		(void)ipc_ser_init(ser);
		ret = ipc_ser_put_32(ser, (uint32_t *)&_err);
		IPC_LOG_ERR("serialization failed.\n");
	}

	if (ret >= 0) {
		ser->header = *(rw_msg_header_t *)pcon;
		ser->header.cid = ser->header.pid;
		ser->header.pid = data->pid;
		ser->header.typ = MSGBX_MSG_TYPE_REPLY;
		ret = ipc_ser_finish(ser);
	}

	if (ret >= 0)
		ret = ipc_trans_layer_stub_send_reply_msg(data->pid, data->handle, ser);

	if (ret < 0) {
		IPC_LOG_ERR("send reply fail %d.\n", ret);
		return ret;
	}

	return RESULT_SUCCESS;
}

static int32_t register_vcan_method(switch0_can_gateway_vcan_method_t func)
{
	if (!s_ext)
		return -ERR_APP_PARAM;
	s_ext->vcan_method_ptr = func;
	return RESULT_SUCCESS;
}

static int32_t call_vcan_method(serdes_t *des)
{
	int32_t ret = 0;
	des_buf_t *buf = NULL;
	uint32_t len = 0;
	com_server_data_t *data = s_data;
	uintptr_t pcon = 0;
	uint8_t command = 0;
	uint32_t param = 0;

	if (!des || !data || !s_ext || !s_ext->vcan_method_ptr)
		return -ERR_APP_PARAM;

	buf = &data->des_buf;
	clear_des_buf(buf);
	len = ipc_des_get_all(des, (uint8_t *)buf->data_buf);
	if (len <= 0)
		return -ERR_APP_SERDES;
	buf->unavail_data_size = IPC_MAX_DATA_SIZE - len;

	if (ret >= 0)
		ret = deserialize_8(buf, (uint8_t *)&command);
	if (ret >= 0)
		ret = deserialize_32(buf, (uint32_t *)&param);

	if (ret < 0)
		return -ERR_APP_SERDES;

	data->info.uuid = ipc_msg_get_uuid(des->header);
	data->info.timestamp = des->recv_end_time;
	pcon = (uintptr_t)&des->header;
	(*s_ext->vcan_method_ptr)(command, param, *(uint64_t *)pcon, &data->info);

	return RESULT_SUCCESS;
}

static int32_t reply_vcan_method(
				const switch0_can_gateway_ErrorEnum_t err,
				const uint64_t context)
{
	int32_t ret = 0;
#ifdef IPC_RTE_BAREMETAL
	serdes_t *ser = NULL;
#else
	serdes_t serdes = { 0 };
	serdes_t *ser = &serdes;
#endif
	com_server_data_t *data = s_data;
	uintptr_t pcon = (uintptr_t)&context;

	if (!data)
		return -ERR_APP_PARAM;
#ifdef IPC_RTE_BAREMETAL
	ser = &data->serializer;
#endif
	ret = ipc_ser_init(ser);
	if (ret >= 0)
		ret = serialize_switch0_can_gateway_ErrorEnum(ser, &err);

	if (ret < 0) {
		int32_t _err = -1;
		(void)ipc_ser_init(ser);
		ret = ipc_ser_put_32(ser, (uint32_t *)&_err);
		IPC_LOG_ERR("serialization failed.\n");
	}

	if (ret >= 0) {
		ser->header = *(rw_msg_header_t *)pcon;
		ser->header.cid = ser->header.pid;
		ser->header.pid = data->pid;
		ser->header.typ = MSGBX_MSG_TYPE_REPLY;
		ret = ipc_ser_finish(ser);
	}

	if (ret >= 0)
		ret = ipc_trans_layer_stub_send_reply_msg(data->pid, data->handle, ser);

	if (ret < 0) {
		IPC_LOG_ERR("send reply fail %d.\n", ret);
		return ret;
	}

	return RESULT_SUCCESS;
}

static int32_t register_can_gateway_send(switch0_can_gateway_can_gateway_send_t func)
{
	if (!s_ext)
		return -ERR_APP_PARAM;
	s_ext->can_gateway_send_ptr = func;
	return RESULT_SUCCESS;
}

static int32_t call_can_gateway_send(serdes_t *des)
{
	int32_t ret = 0;
	des_buf_t *buf = NULL;
	uint32_t len = 0;
	com_server_data_t *data = s_data;
	uintptr_t pcon = 0;
	switch0_can_gateway_UInt8Array128_t *x2can = NULL;

	if (!des || !data || !s_ext || !s_ext->can_gateway_send_ptr)
		return -ERR_APP_PARAM;

	buf = &data->des_buf;
	clear_des_buf(buf);
	len = ipc_des_get_all(des, (uint8_t *)buf->data_buf);
	if (len <= 0)
		return -ERR_APP_SERDES;
	buf->unavail_data_size = IPC_MAX_DATA_SIZE - len;

	if (ret >= 0)
		ret = deserialize_switch0_can_gateway_UInt8Array128(buf, &x2can);

	if (ret < 0)
		return -ERR_APP_SERDES;

	data->info.uuid = ipc_msg_get_uuid(des->header);
	data->info.timestamp = des->recv_end_time;
	pcon = (uintptr_t)&des->header;
	(*s_ext->can_gateway_send_ptr)(x2can, *(uint64_t *)pcon, &data->info);

	return RESULT_SUCCESS;
}

static int32_t reply_can_gateway_send(
				const switch0_can_gateway_ErrorEnum_t err,
				const uint64_t context)
{
	int32_t ret = 0;
#ifdef IPC_RTE_BAREMETAL
	serdes_t *ser = NULL;
#else
	serdes_t serdes = { 0 };
	serdes_t *ser = &serdes;
#endif
	com_server_data_t *data = s_data;
	uintptr_t pcon = (uintptr_t)&context;

	if (!data)
		return -ERR_APP_PARAM;
#ifdef IPC_RTE_BAREMETAL
	ser = &data->serializer;
#endif
	ret = ipc_ser_init(ser);
	if (ret >= 0)
		ret = serialize_switch0_can_gateway_ErrorEnum(ser, &err);

	if (ret < 0) {
		int32_t _err = -1;
		(void)ipc_ser_init(ser);
		ret = ipc_ser_put_32(ser, (uint32_t *)&_err);
		IPC_LOG_ERR("serialization failed.\n");
	}

	if (ret >= 0) {
		ser->header = *(rw_msg_header_t *)pcon;
		ser->header.cid = ser->header.pid;
		ser->header.pid = data->pid;
		ser->header.typ = MSGBX_MSG_TYPE_REPLY;
		ret = ipc_ser_finish(ser);
	}

	if (ret >= 0)
		ret = ipc_trans_layer_stub_send_reply_msg(data->pid, data->handle, ser);

	if (ret < 0) {
		IPC_LOG_ERR("send reply fail %d.\n", ret);
		return ret;
	}

	return RESULT_SUCCESS;
}

// broadcast

static int32_t register_can_gateway_recv_subcribed(broadcast_sub_t func)
{
	if (!s_ext)
		return -ERR_APP_PARAM;
	s_ext->can_gateway_recv_sub_ptr = func;
	return RESULT_SUCCESS;
}

static int32_t register_can_gateway_recv_unsubcribed(broadcast_sub_t func)
{
	if (!s_ext)
		return -ERR_APP_PARAM;
	s_ext->can_gateway_recv_unsub_ptr = func;
	return RESULT_SUCCESS;
}

static int32_t can_gateway_recv(broadcast_reg_entry_t *entries, uint32_t size)
{
	int32_t ret = 0;
	int32_t send_ret = 0;
	int32_t index = 0;
	rw_msg_header_t header = { 0 };
	broadcast_reg_entry_t *entry = entries;
#ifdef IPC_RTE_BAREMETAL
	serdes_t *ser = NULL;
#else
	serdes_t serdes = { 0 };
	serdes_t *ser = &serdes;
#endif
	com_server_data_t *data = s_data;

	if (!data || !s_ext)
		return -ERR_APP_PARAM;
#ifdef IPC_RTE_BAREMETAL
	ser = &data->serializer;
#endif
	header.pid = data->pid;
	header.cmd = CMD_BROADCAST_CAN_GATEWAY_RECV;
	header.typ = MSGBX_MSG_TYPE_BROADCAST;
	ret = ipc_ser_init(ser);

	if (ret < 0)
		return -ERR_APP_SERDES;

	if (!entry || size == 0) {
		broadcast_registry_t *reg = &s_ext->can_gateway_recv_registry;
		entry = reg->entries + reg->start;
		size = reg->end - reg->start;
	}
	for (index = 0; index < size; ++index, ++entry) {
		if (entry->pid != 0) {
			header.cid = entry->pid;
			header.fid = entry->fid;
			header.sid = entry->sid;
			header.tok = data->token;
			ipc_ser_set_header(ser, header);
			ipc_ser_finish(ser);
			send_ret = ipc_trans_layer_stub_send_broadcast(data->pid, data->handle, ser);
			if (send_ret < 0)
				IPC_LOG_ERR("send broadcast fail %d.\n", send_ret);
			else
				++ret;
		}
	}
	increase_token(data);
	return ret;
}

// dispatch_request
static int32_t dispatch_request(serdes_t *des, bool *reply)
{
	int32_t ret = 0;

	if (!des)
		return -ERR_APP_PARAM;

	switch (des->header.cmd) {
	case CMD_METHOD_NOTIFY_ETH_2_CAN_ENQUEUE:
		ret = call_notify_Eth_2_Can_enqueue(des);
		*reply = false;
		return ret;
	case CMD_METHOD_NOTIFY_ETH_2_CAN_DEQUEUE:
		ret = call_notify_Eth_2_Can_dequeue(des);
		*reply = false;
		return ret;
	case CMD_METHOD_NOTIFY_CAN_2_ETH_ENQUEUE:
		ret = call_notify_Can_2_Eth_enqueue(des);
		*reply = false;
		return ret;
	case CMD_METHOD_NOTIFY_CAN_2_ETH_DEQUEUE:
		ret = call_notify_Can_2_Eth_dequeue(des);
		*reply = false;
		return ret;
	case CMD_METHOD_VMAC_METHOD:
		ret = call_vmac_method(des);
		if (ret >= 0)
			*reply = false;
		else
			*reply = true;
		return ret;
	case CMD_METHOD_GET_ETH_STATISTICS:
		ret = call_get_ETH_statistics(des);
		if (ret >= 0)
			*reply = false;
		else
			*reply = true;
		return ret;
	case CMD_METHOD_VCAN_METHOD:
		ret = call_vcan_method(des);
		if (ret >= 0)
			*reply = false;
		else
			*reply = true;
		return ret;
	case CMD_METHOD_CAN_GATEWAY_SEND:
		ret = call_can_gateway_send(des);
		if (ret >= 0)
			*reply = false;
		else
			*reply = true;
		return ret;
	case CMD_METHOD_SUB_CAN_GATEWAY_RECV:
		if (s_ext->can_gateway_recv_sub_ptr)
			ret = (*s_ext->can_gateway_recv_sub_ptr)((uint8_t)des->header.pid,
					(uint8_t)des->header.fid, (uint8_t)des->header.sid);
		if (ret >= 0)
			ret = add_registration(&s_ext->can_gateway_recv_registry,
					(uint8_t)des->header.pid, (uint8_t)des->header.fid,
					(uint8_t)des->header.sid);
		*reply = true;
		return ret;
	case CMD_METHOD_UNSUB_CAN_GATEWAY_RECV:
		if (s_ext->can_gateway_recv_unsub_ptr)
			ret = (*s_ext->can_gateway_recv_unsub_ptr)((uint8_t)des->header.pid,
					(uint8_t)des->header.fid, (uint8_t)des->header.sid);
		if (ret >= 0)
			ret = remove_registration(&s_ext->can_gateway_recv_registry,
					(uint8_t)des->header.pid, (uint8_t)des->header.fid,
					(uint8_t)des->header.sid);
		*reply = true;
		return ret;
	default:
		break;
	}
	ret = -ERR_APP_UNKNOWN_CMD;
	*reply = false;
	return ret;
}

// initialize server
int32_t switch0_can_gateway_server_init(com_server_data_t *data, switch0_can_gateway_server_t *server,
			switch0_can_gateway_server_ext_t *ext)
{
	int32_t ret = 0;

	if (!data || !server || !ext)
		return -1;

	s_data = data;
	s_ext = ext;

	// register CMDs.
	ret = ipc_trans_layer_register_method(data->pid, data->handle, CMD_METHOD_NOTIFY_ETH_2_CAN_ENQUEUE);
	if (ret < 0)
		return -1;
	ret = ipc_trans_layer_register_method(data->pid, data->handle, CMD_METHOD_NOTIFY_ETH_2_CAN_DEQUEUE);
	if (ret < 0)
		return -1;
	ret = ipc_trans_layer_register_method(data->pid, data->handle, CMD_METHOD_NOTIFY_CAN_2_ETH_ENQUEUE);
	if (ret < 0)
		return -1;
	ret = ipc_trans_layer_register_method(data->pid, data->handle, CMD_METHOD_NOTIFY_CAN_2_ETH_DEQUEUE);
	if (ret < 0)
		return -1;
	ret = ipc_trans_layer_register_method(data->pid, data->handle, CMD_METHOD_VMAC_METHOD);
	if (ret < 0)
		return -1;
	ret = ipc_trans_layer_register_method(data->pid, data->handle, CMD_METHOD_GET_ETH_STATISTICS);
	if (ret < 0)
		return -1;
	ret = ipc_trans_layer_register_method(data->pid, data->handle, CMD_METHOD_VCAN_METHOD);
	if (ret < 0)
		return -1;
	ret = ipc_trans_layer_register_method(data->pid, data->handle, CMD_METHOD_CAN_GATEWAY_SEND);
	if (ret < 0)
		return -1;
	ret = ipc_trans_layer_register_method(data->pid, data->handle, CMD_METHOD_SUB_CAN_GATEWAY_RECV);
	if (ret < 0)
		return -1;
	ret = ipc_trans_layer_register_method(data->pid, data->handle, CMD_METHOD_UNSUB_CAN_GATEWAY_RECV);
	if (ret < 0)
		return -1;

	// set server
	server->version = get_ipc_inf_version;
	ext->notify_Eth_2_Can_enqueue_ptr = NULL;
	server->register_notify_Eth_2_Can_enqueue = register_notify_Eth_2_Can_enqueue;
	ext->notify_Eth_2_Can_dequeue_ptr = NULL;
	server->register_notify_Eth_2_Can_dequeue = register_notify_Eth_2_Can_dequeue;
	ext->notify_Can_2_Eth_enqueue_ptr = NULL;
	server->register_notify_Can_2_Eth_enqueue = register_notify_Can_2_Eth_enqueue;
	ext->notify_Can_2_Eth_dequeue_ptr = NULL;
	server->register_notify_Can_2_Eth_dequeue = register_notify_Can_2_Eth_dequeue;
	ext->vmac_method_ptr = NULL;
	server->register_vmac_method = register_vmac_method;
	server->reply_vmac_method = reply_vmac_method;
	ext->get_ETH_statistics_ptr = NULL;
	server->register_get_ETH_statistics = register_get_ETH_statistics;
	server->reply_get_ETH_statistics = reply_get_ETH_statistics;
	ext->vcan_method_ptr = NULL;
	server->register_vcan_method = register_vcan_method;
	server->reply_vcan_method = reply_vcan_method;
	ext->can_gateway_send_ptr = NULL;
	server->register_can_gateway_send = register_can_gateway_send;
	server->reply_can_gateway_send = reply_can_gateway_send;

	server->can_gateway_recv = can_gateway_recv;
	server->register_can_gateway_recv_subcribed = register_can_gateway_recv_subcribed;
	server->register_can_gateway_recv_unsubcribed = register_can_gateway_recv_unsubcribed;

	server->dispatch_request = dispatch_request;

	return 0;
}

// destroy client
void switch0_can_gateway_server_destroy(void)
{
	s_data = NULL;
	s_ext = NULL;
}
